#!/usr/bin/python
import json , sys , os.path , time
from copy import deepcopy
from grouppulse import *
from comparer import *
from faultsanalyzer import *

__author__ = 'meirdrago'

#       INITIALIZED WHEN NEW GROUP WAS ASSIGNED OR UPDATED
class GroupManager(object):

	RUNNER = True

        def __init__(self,name,group_conf,compare_conf,parser,logger):
		self.name		= name
                self.group_conf         = group_conf
                self.compare_conf       = compare_conf
                self.schedular          = {}
                self.Pulses             = {}
		self.faults 		= {}
		self.parser		= parser
		self.logger		= logger
                for epoc in self.group_conf["epocs"]:
                        self.Pulses[epoc] = GroupPulse(self.group_conf)
                        self.schedular[epoc] = 0


        #       TRIGGERED BY OUTSIDE
        def pulse(self):
		self.RUNNER = False		
		self.Pulses[0].arithmetics()
                self.faults = {}

		if "monitor" in self.group_conf:
			self.logger._log("groups.log" , "GROUP %s\tdigested rows = %s , incorrect rows = %s" % (self.name,self.good_rows,self.bad_rows))
			self.logger._log("monitor.log" , "%s\t%s" % (self.name , self.Pulses[0].Persist )) 
			return	

                for epoc in self.group_conf["epocs"]:

                        C = Comparer(self.compare_conf, self.Pulses[epoc].Persist , self.Pulses[0].Persist , 1)
                        C.compare(True)
			self.logger._log("groups.log" , "%s\tCOMPARE results:\t%s" % (self.name , ",".join([(k + "=" + str(C.report[k])) for k in C.report])))
			
                        for k in C.Persist :
                                for f in C.Persist[k] :
                                        #       SAVE PER EPOC
                                        if not k in self.faults : self.faults[k] = {}
                                        self.faults[k][f] = 1 if not f in self.faults[k] else self.faults[k][f] + 1

                        #       RESTART COUNTERS AND TRUNCATE Persist OBJECTS
                        if self.schedular[epoc] == epoc :
                                self.schedular[epoc] = 0
                                self.Pulses[epoc].Persist = {}
                        #       MERGE DATA WITH CURRENT
                        self.Pulses[epoc].mergeWith( self.Pulses[0].Persist  )
                        self.schedular[epoc] += 1
                self.analize()
		self.logger._log("groups.log" , "GROUP %s\tdigested rows = %s , incorrect rows = %s" % (self.name,self.good_rows,self.bad_rows))



	def get_IO_resource(self , hostId=None):

		# 	SSH
		if "ssh" in self.group_conf:
			try : 
				import paramiko
			except :
				self.logger._log("groups.log" , "NO MODULE paramiko. Please Install. Group IGNORED")
			try :
				ssh = paramiko.SSHClient()
				ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
				host = self.group_conf["ssh"]["hosts"][hostId] if "hosts" in self.group_conf["ssh"] and len(self.group_conf["ssh"]["hosts"]) == 2 else self.group_conf["ssh"]["host"]
				ssh.connect(host , username=self.group_conf["ssh"]["user"] , password=self.group_conf["ssh"]["passwd"])
				return ssh

			except :
				self.logger._log("groups.log" , "SSH AUTH PROBLEM in group %s. Group IGNORED" % (self.name))
				
		#	LOCAL FILE
		else :
			file = self.group_conf["files"][hostId] if "files" in self.group_conf and len(self.group_conf["files"]) == 2 else self.group_conf["file"]
			return open(file)


	def run(self , hostId=None):
		self.RUNNER = True
                self.bad_rows   = 0
                self.good_rows  = 0
		self.Pulses[0] 	= GroupPulse(self.group_conf)
		try :
			f		= self.get_IO_resource(hostId)
			if "ssh" in self.group_conf:
				stdin, stdout , stderr = f.exec_command("tail -f %s" % (self.group_conf["file"]))
		except :
			self.logger._log("groups.log" , "in group %s Cant open file %s. SKKIPING" % (self.name , self.group_conf["file"]))
			return False
		while self.RUNNER:
			line = stdout.readline() if "ssh" in self.group_conf else f.readline()
			if len(line) > 0:
                                try :
					parsed_line = self.parser.do_parse(line)
					if parsed_line and len(parsed_line.keys()) > 0:
						pulse_id =  hostId if  hostId else 0	
						self.Pulses[pulse_id].in_line( parsed_line )
        	                                self.good_rows  += 1
                                except :
                                        self.bad_rows   += 1
			else :
				if "file" in self.group_conf or "files" in self.group_conf :
					self.RUNNER = False
				time.sleep(0.1)
			if not self.RUNNER: 
				f.close()


	def single(self , cmd):
		self.bad_rows   = 0
                self.good_rows  = 0
                self.Pulses[0]  = GroupPulse(self.group_conf)
                try :
                        f               = self.get_IO_resource()
                        if "ssh" in self.group_conf:
                                stdin, stdout , stderr 	= f.exec_command("%s %s" % (cmd,self.group_conf["file"]))
				
                except :
                        self.logger._log("groups.log" , "in group %s Cant open file %s. SKKIPING" % (self.name , self.group_conf["file"]))
                        return False
		fp = stdout if "ssh" in self.group_conf else f
		for line in fp :
                        if len(line) > 0:
                                try :
                                        parsed_line = self.parser.do_parse(line)
                                        if parsed_line and len(parsed_line.keys()) > 0:
                                                self.Pulses[0].in_line( parsed_line )
                                                self.good_rows  += 1
                                except :
                                        self.bad_rows   += 1
		f.close()
		self.pulse()	


        def analize(self):
                self.faultAnz = FaultsAnalyzer(self.group_conf , self.faults)
                self.faultAnz.do_process()
		self.print_alerts()


        def print_alerts(self):
                for k in self.faultAnz.alertdata :
			for ff in self.faultAnz.alertdata[k]:
				if len(self.faultAnz.alertdata[k][ff].keys()) > 0:
					self.logger._log("results.log","%s\t%s\t%s" % (self.name , ff , ":".join(self.faultAnz.alertdata[k][ff].keys())))
	

############################################################

class PairGroupManager( GroupManager ):

	def __init__(self,name,group_conf,compare_conf,parser,logger):
		group_conf["epocs"] = [0,1]
		super(PairGroupManager,self).__init__(name,group_conf,compare_conf,parser,logger)

        def pulse(self):
                self.RUNNER = False
                self.Pulses[0].arithmetics()
                self.Pulses[1].arithmetics()
                self.faults = {}

		#	COMPARE MASTER (0) VS. SLAVE (1)
		print "Pulses master rows = %s , Slave = %s" % (len(self.Pulses[0].Persist.keys())  ,  len(self.Pulses[1].Persist.keys()))
		C = Comparer(self.compare_conf, self.Pulses[0].Persist , self.Pulses[1].Persist , 1)
		C.compare(True)
		self.logger._log("groups.log" , "%s\tCOMPARE results:\t%s" % (self.name , ",".join([(k + "=" + str(C.report[k])) for k in C.report])))
                for k in C.Persist :
                	for f in C.Persist[k] :
                         	#       SAVE PER EPOC
                           	if not k in self.faults : self.faults[k] = {}
                              	self.faults[k][f] = 1 if not f in self.faults[k] else self.faults[k][f] + 1
		self.Pulses[0].Persist = {}
		self.Pulses[1].Persist = {}
		self.analize()
		self.logger._log("groups.log" , "GROUP %s\tdigested rows = %s , incorrect rows = %s" % (self.name,self.good_rows,self.bad_rows))

